package com.ygqh.baby.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ygqh.baby.ao.*;
import com.ygqh.baby.mapper.YgCardCouponDetailMapper;
import com.ygqh.baby.model.*;
import com.ygqh.baby.model.wdt.qyb.WdtQybResult;
import com.ygqh.baby.po.*;
import com.ygqh.baby.service.*;
import com.ygqh.baby.service.wdtqyb.api.WdtQybApi;
import com.ygqh.baby.utils.*;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class YgCardCouponDetailServiceImpl implements YgCardCouponDetailService {
    protected final Logger logger = Logger.getLogger(this.getClass());
    @Autowired
    private YgCardCouponDetailMapper ygCardCouponDetailMapper;
    @Autowired
    private YgCardCouponService ygCardCouponService;
    @Autowired
    private YgUserService ygUserService;
    @Autowired
    private YgCouponService ygCouponService;
    @Autowired
    private YgOrderService ygOrderService;
    @Autowired
    private WdtQybApi wdtQybApi;
    @Autowired
    private YgUserBalanceService ygUserBalanceService;
    @Autowired
    private YgSkuService ygSkuService;
    @Autowired
    private YgOrderDetailService ygOrderDetailService;
    @Autowired
    private YgStockService ygStockService;
    @Autowired
    private YgFrameCodeService ygFrameCodeService;
    @Autowired
    private YgCardGiveRecordService ygCardGiveRecordService;
    @Autowired
    private YgProductService ygProductService;
    @Autowired
    private YgProductImagesService ygProductImagesService;
    @Autowired
    private YgUserMemberService ygUserMemberService;
    @Autowired
    private ThreadPool threadPool;
    @Autowired
    private WxMpMessageService wxMpMessageService;
    @Autowired
    private WxSmallMessageService wxSmallMessageService;
    @Autowired
    private YgOrderPaymentService ygOrderPaymentService;
    @Autowired
    private MailUtil mailUtil;

    @Override
    public List<YgCardCouponDetail> find() {
        YgCardCouponDetailExample example = new YgCardCouponDetailExample();
        example.createCriteria().andStatusEqualTo(DataStatus.Valid.name());
        return ygCardCouponDetailMapper.selectByExample(example);
    }

    @Override
    public int findCount() {
        YgCardCouponDetailExample example = new YgCardCouponDetailExample();
        example.createCriteria().andStatusEqualTo(DataStatus.Valid.name());
        return ygCardCouponDetailMapper.countByExample(example);
    }

    @Override
    public YgCardCouponDetail findById(Long id) {
        return ygCardCouponDetailMapper.selectByPrimaryKey(id);
    }

    @Override
    public YgCardCouponDetail findById(Long id, Long userId) {
        YgCardCouponDetailExample example = new YgCardCouponDetailExample();
        example.createCriteria().andStatusEqualTo(DataStatus.Valid.name()).andIdEqualTo(id).andUserIdEqualTo(userId);
        List<YgCardCouponDetail> list = ygCardCouponDetailMapper.selectByExample(example);
        if (CollectionUtils.isEmpty(list)) {
            return null;
        }
        return list.get(0);
    }

    @Override
    public int save(YgCardCouponDetail ygCardCouponDetail) {
        return ygCardCouponDetailMapper.insertSelective(ygCardCouponDetail);
    }

    @Override
    public int update(YgCardCouponDetail ygCardCouponDetail) {
        return ygCardCouponDetailMapper.updateByPrimaryKeySelective(ygCardCouponDetail);
    }

    @Override
    public ResultSet<YgCardCouponDetail> search(QueryInfo queryInfo, CardType cardType, CardMode cardMode, Date startDate, Date endDate, String q) {
        List<YgCardCouponDetail> list = ygCardCouponDetailMapper.selectSuper(queryInfo, cardType, cardMode, startDate, endDate, q);
        int count = ygCardCouponDetailMapper.countSuper(cardType, cardMode, startDate, endDate, q);
        ResultSet<YgCardCouponDetail> resultSet = new ResultSet<YgCardCouponDetail>(count, list);
        return resultSet;
    }

    @Override
    public int deleteSoft(Long[] ids) {
        Assert.notEmpty(ids);
        YgCardCouponDetailExample example = new YgCardCouponDetailExample();
        example.createCriteria().andIdIn(Arrays.asList(ids));
        YgCardCouponDetail record = new YgCardCouponDetail();
        record.setStatus(DataStatus.Delete);

        return ygCardCouponDetailMapper.updateByExampleSelective(record, example);
    }

    @Override
    public int deleteSoft(Long id) {
        return this.deleteSoft(new Long[]{id});
    }

    @Override
    public int saveOrUpdate(YgCardCouponDetail ygCardCouponDetail) {
        int r = 0;
        if (ygCardCouponDetail.getId() != null) {
            r = this.update(ygCardCouponDetail);
        } else {
            r = this.save(ygCardCouponDetail);
        }
        return r;
    }

    @Override
    public List<YgCardCouponInfo> findCardInfoByUserId(Long userId, UseStatus useStatus) {
        return ygCardCouponDetailMapper.selectCardInfoByUserId(null, userId, useStatus == null ? null : useStatus.name());
    }

    @Override
    public YgCardCouponInfo findCardInfo(Long cardDetailId, Long userId) {
        List<YgCardCouponInfo> list = ygCardCouponDetailMapper.selectCardInfoByUserId(cardDetailId, userId, null);
        if (!CollectionUtils.isEmpty(list)) {
            return list.get(0);
        }
        return null;
    }

    @Override
    public int saveCardCouponDetail(Long userId, YgCardCoupon cardCoupon, Long paymentCode, String remark) {

        String productName = null;
        String color = null;
        String imagePath = null;
        BigDecimal price = null;
        UseStatus useStatus = UseStatus.UnUsed;

        if (cardCoupon.getCardMode().equals(CardMode.Goods)) {
            long pId = Long.parseLong(cardCoupon.getProductIds());
            YgProduct product = ygProductService.findById(pId);
            YgProductImages images = ygProductImagesService.findMainImgByProductId(pId);
            productName = product.getProductName().replace("【", "").replace("】", "").replace("预售", "");
            color = product.getShortName();
            imagePath = images.getImagePath();
            price = product.getProductSalePrice();

        } else if (cardCoupon.getCardMode().equals(CardMode.BalancePrice)) {
            price = cardCoupon.getBalancePrice();
            useStatus = UseStatus.Used;
        } else if (cardCoupon.getCardMode().equals(CardMode.Card)) {
            useStatus = UseStatus.UnUsed;
            price = new BigDecimal("10.00");
            productName = cardCoupon.getTitle();
        } else {
            YgCoupon coupon = ygCouponService.findById(cardCoupon.getCouponId());
            price = coupon.getFaceValue();
            productName = coupon.getCouponTitle();
            useStatus = UseStatus.Used;
        }
        YgCardCouponDetail detail = new YgCardCouponDetail();
        detail.setCardType(cardCoupon.getCardType());
        detail.setCardMode(cardCoupon.getCardMode());
        detail.setCardId(cardCoupon.getId());
        detail.setRelationId(paymentCode);
        detail.setProductName(productName);
        detail.setColor(color);
        detail.setPrice(price);
        detail.setImagePath(imagePath);
        detail.setCreateTime(new Date());
        detail.setUserId(userId);
        detail.setRemark(remark);
        detail.setSource(CardSource.System);
        if (useStatus.equals(UseStatus.Used)) {
            detail.setUseStatus(useStatus);
            detail.setUseTime(detail.getUseTime());
        }

        setCardDetailValidDate(detail, cardCoupon);
        int i = this.save(detail);
        return i;
    }

    /**
     * 配置卡券明细的有效日期
     *
     * @param detail
     * @param cardCoupon
     */
    private void setCardDetailValidDate(YgCardCouponDetail detail, YgCardCoupon cardCoupon) {
        Date now = new Date();
        switch (cardCoupon.getCardType()) {
            case QueenGift:
            case BirthdayGift:
                YgUserMember userMember = ygUserMemberService.findByUserId(detail.getUserId());
                detail.setStartDate(userMember.getMemberStartTime());
                detail.setEndDate(userMember.getMemberEndTime());
                break;
            case KanJia:
                detail.setStartDate(now);
                detail.setEndDate(DateConvertUtils.addDay(now, cardCoupon.getCardCountDown()));
                break;
            case PullNew:
            case DrawPrize:
            case BasicsGift:
            case ShareReward:
            case OrderGift:
            default:

                detail.setStartDate(now);
                detail.setEndDate(DateConvertUtils.addDay(now, 29));
                break;
        }
    }

    @Override
    public Message cashCard(Long cardDetailId, Long userId, YgUserAddress address) {
        YgCardCouponInfo card = this.findCardInfo(cardDetailId, userId);
        if (card == null) {
            Message.error("亲，您没有此卡券", cardDetailId);
        }
        if (card.getUseStatus().equals(UseStatus.Used)) {
            logger.warn("该卡券已经兑换过；cardDetailId=" + cardDetailId);
            return Message.error("亲，请不要重复兑换", cardDetailId);
        }
        Date dateStart = DateConvertUtils.getDateStart(new Date());
        if (dateStart.before(card.getEndDate())) {
            logger.warn("该卡券已过期；cardDetailId=" + cardDetailId);
            return Message.error("亲，该卡券已过期", cardDetailId);
        }
        Long orderId = null;
        if (card.getCardMode().equals(CardMode.BalancePrice)) {
            ygUserBalanceService.incomeRecharge(userId, card.getBalancePrice(), OperationType.CardCoupon, cardDetailId.toString(), "卡券兑现", "sys");
        } else if (card.getCardMode().equals(CardMode.Coupon)) {
            YgUser user = ygUserService.findById(userId);
            if (card.getCardType().equals(CardType.BasicsGift)) {
                // 给会员券
                ygUserMemberService.sendQueenCoupon(user, card.getCouponId());
            } else {
                sendCoupon(card.getCouponId(), user, "女王,优惠券已奉上,请查收！");
            }
        } else if (card.getCardMode().equals(CardMode.Goods)) {
            // 取消掉旧的订单，生成并推送新订单，回写关联id
            orderId = ygFrameCodeService.getFrameCode(CodeType.RechargeMB, new Date());
            OrderStatus orderStatus = null;
            BigDecimal totalPrice = BigDecimal.ZERO;
            if (CardType.PullNew.equals(card.getCardType()) && card.getPrice().compareTo(BigDecimal.ZERO) > 0) {
                // 需要付费购买的拉新活动卡券，订单状态为待付款
                orderStatus = OrderStatus.WaitingPay;
                totalPrice = card.getPrice();
            }
            syncOrderByCashCard(userId, cardDetailId, orderId, card.getRelationId(), address, card.getProductIds(), totalPrice, totalPrice,
                    AppType.WeChat, PayType.Account, orderStatus);
        }
        YgCardCouponDetail ygCardCouponDetail = new YgCardCouponDetail();
        ygCardCouponDetail.setId(cardDetailId);
        ygCardCouponDetail.setUseStatus(UseStatus.Used);
        ygCardCouponDetail.setUseTime(new Date());
        this.update(ygCardCouponDetail);
        return Message.success(orderId);
    }

    private void sendCoupon(Long couponId, YgUser user, String titl) {
        // 给会员券
        YgCoupon coupon = ygCouponService.findById(couponId);

        Date start = new Date();
        Date end = coupon.getEndDate();
        for (int i = 0; i < coupon.getLeadNum(); i++) {
            ygCouponService.receiveCouponBatchV2(couponId.toString(), end, user);
        }

        String link = "/user/coupon.html";
        String remark = "到我的优惠券看看吧。";
        String[] keyword = new String[]{user.getUserName(), "有效期 " + DateConvertUtils.format(start) + "至" + DateConvertUtils.format(end)};
        wxMpMessageService.sendBindMsg(titl, link, remark, user, keyword);

    }

    private void syncOrderByCashCard(Long userId, Long cardDetailId, Long orderId, Long oldOrderId, YgUserAddress address, String productIds, BigDecimal totalPrice,
                                     BigDecimal expressPrice, AppType appType, PayType payType, OrderStatus orderStatus) {
        threadPool.getExecutorService().execute(() -> {

            try {
                YgOrder ygOrder = ygOrderService.findOrderDetailByOrderId(oldOrderId, DataStatus.Delete);
                Map<Long, List<YgOrderDetail>> map = ygOrder.getOrderDetail().stream().collect(Collectors.groupingBy(YgOrderDetail::getSkuId));
                List<YgSkuInfo> skuList = ygSkuService.findSkuInfoListByIds(new ArrayList<>(map.keySet()));
                skuList.forEach(o -> o.setQuantity(map.get(o.getSkuId()).get(0).getQuantity()));
                YgOrder order = saveGoodsCardOrder(userId, orderId, address, DataStatus.Valid, ygOrder.getParentId(), false, ygOrder.getSourceCode(),
                        totalPrice, expressPrice, appType, payType, orderStatus, skuList.toArray(new YgSkuInfo[0]));
                updateRelationId(cardDetailId, orderId);
                order = ygOrderService.findOrderDetailByOrderId(orderId, DataStatus.Valid);
                WdtQybResult wdtQybResult = wdtQybApi.tradePush(order);
                ygOrderService.updateWdtCodeBatch(wdtQybResult.getPushSuccessList());
            } catch (Exception e) {
                logger.error(ExceptionUtil.getExceptionMsg(e));
                e.printStackTrace();
            }

        });

    }

    @Override
    public int updateRelationId(Long cardDetailId, Long relationId) {
        YgCardCouponDetail cardCouponDetail = new YgCardCouponDetail();
        cardCouponDetail.setId(cardDetailId);
        cardCouponDetail.setRelationId(relationId);
        return this.update(cardCouponDetail);

    }


    @Override
    public YgOrder saveGoodsCardOrder(Long userId, Long paymentCode, YgUserAddress addressInfo, DataStatus dataStatus, Long parentId, boolean reduceStock,
                                      String sourceCode, YgSkuInfo... skuInfos) {
        return saveGoodsCardOrder(userId, paymentCode, addressInfo, dataStatus, parentId, reduceStock, sourceCode, BigDecimal.ZERO, BigDecimal.ZERO,
                AppType.WeChat, PayType.Account, null, skuInfos);
    }

    private YgOrder saveGoodsCardOrder(Long userId, Long paymentCode, YgUserAddress addressInfo, DataStatus dataStatus, Long parentId, boolean reduceStock,
                                       String sourceCode, BigDecimal totalPrice, BigDecimal expressPrice,
                                       AppType appType, PayType payType, OrderStatus orderStatus, YgSkuInfo... skuInfos) {


        BigDecimal zero = new BigDecimal("0.00");
        // Long quantity = 1L;

        YgOrder order = new YgOrder();
        // 设置收货信息
        order.setReceiver(addressInfo.getReceiver());
        order.setTelPhone(addressInfo.getTelPhone());
        order.setProvinceName(addressInfo.getProvinceName());
        order.setCityName(addressInfo.getCityName());
        order.setAreaName(addressInfo.getAreaName());
        order.setAddress(addressInfo.getAddress());
        // 保存主单

        order.setOrderId(paymentCode);
        order.setParentId(parentId == null ? paymentCode : parentId);
        order.setUserId(userId);
        order.setTotalPrice(totalPrice);
        order.setProductPrice(zero);
        order.setExpressPrice(expressPrice);
        order.setManjianPrice(zero);
        order.setYouhuijuanPrice(zero);
        order.setGroupDisPrice(zero);
        order.setNewCustomDisPrice(zero);
        order.setPackDisPrice(zero);
        order.setBmdisPrice(zero);
        order.setAppType(appType);
        order.setPayType(payType);
        order.setSupplierId(skuInfos[0].getSupplierId());
        if (DataStatus.Delete.equals(dataStatus)) {
            order.setOrderStatus(OrderStatus.WaitingPay);
            order.setPaidPrice(zero);
        } else if (OrderStatus.WaitingPay.equals(orderStatus)) {
            order.setOrderStatus(OrderStatus.WaitingPay);
            order.setPaidPrice(zero);
        } else {
            order.setOrderStatus(OrderStatus.WaitingSend);
            order.setPaidTime(new Date());
            order.setPaidPrice(totalPrice);
        }
        order.setCreateTime(new Date());
        order.setAccountPrice(zero);
        order.setOrderType(OrderType.CardCoupon);
        order.setStatus(dataStatus);
        order.setSourceCode(sourceCode);
        List<YgStock> stocks = new ArrayList<YgStock>();

        List<YgOrderDetail> detailList = new ArrayList<YgOrderDetail>();

        for (YgSkuInfo skuInfo : skuInfos) {
            Long quantity = skuInfo.getQuantity() == null ? 1L : skuInfo.getQuantity();
            YgOrderDetail detail = new YgOrderDetail();
            detail.setOrderId(paymentCode);
            detail.setProductName(skuInfo.getProductName());
            detail.setPromotionType(PromotionType.ManZeng);
            detail.setQuantity(quantity);
            detail.setSize(skuInfo.getSizeName());
            detail.setSupplierId(skuInfo.getSupplierId());
            detail.setSkuCode(skuInfo.getSkuCode());
            detail.setSkuId(skuInfo.getSkuId());
            detail.setUnitName(skuInfo.getUnitName());
            detail.setImageUrl(skuInfo.getImgPath());
            detail.setShortName(skuInfo.getShortName());

            detail.setSalePrice(BigDecimal.ZERO);
            detail.setMjDisPrice(BigDecimal.ZERO);
            detail.setYhqDisPrice(BigDecimal.ZERO);
            detail.setBmDisPrice(BigDecimal.ZERO);
            detail.setPackDisPrice(BigDecimal.ZERO);
            detail.setNewCustomDisPrice(BigDecimal.ZERO);
            detail.setVipDisPrice(BigDecimal.ZERO);
            detail.setExpressPrice(BigDecimal.ZERO);
            detail.setAccountPrice(BigDecimal.ZERO);
            detail.setCostPrice(skuInfo.getCostPrice());


            detailList.add(detail);

            YgStock stock = new YgStock();
            stock.setSkuCode(skuInfo.getSkuCode());
            stock.setAmount(quantity);
            stocks.add(stock);
        }

        try {
            ygOrderService.save(order);
            ygOrderDetailService.addBatch(detailList);
            order.setOrderDetail(detailList);
            // 扣减库存
            if (reduceStock) {
                ygStockService.reduceStock(stocks, "saveGoodsCardOrder");
            }
        } catch (Exception e) {
            logger.error("订单保存失败。orderInfo:" + order.toString());
            e.printStackTrace();
            return null;
        }

        return order;

    }

    @Override
    public Message generateCardCouponBatch(Long userId, String cardIds, Long paymentCode, String remark) {
        String[] split = cardIds.split(",");
        for (int i = 0; i < split.length; i++) {
            Long cardId = Long.parseLong(split[i]);

            this.generateCardCoupon(userId, cardId, paymentCode, remark);
        }
        return Message.success(null);
    }

    private Message checkCardCouponBeforeGenerate(Long userId, YgCardCoupon cardCoupon) {
        if (cardCoupon.getCardMode().equals(CardMode.Goods)) {
            List<YgSku> list = ygSkuService.find(Long.parseLong(cardCoupon.getProductIds()));
            if (CollectionUtils.isEmpty(list)) {
                return Message.error("赠品不存在", null);
            }
            YgStock stock = ygStockService.findBySkuCode(list.get(0).getSkuCode());
            if (stock.getAmount().compareTo(1L) < 0) {
                logger.warn("赠品库存不足兑换失败；userId =" + userId + ";cardId=" + cardCoupon.getId());
                sendMailMsg("赠品库存不足兑换失败；userId =" + userId + ";cardId=" + cardCoupon.getId());
                return Message.error("亲，您来晚了，赠品已送完", null);
            }
        }

        // 基础卡券，现只有优惠券类型，用于成为女王赠送的优惠券。不生成卡券
        if (cardCoupon.getCardType().equals(CardType.BasicsGift)) {
            logger.warn("基础类型，不生成卡券；userId=" + userId);
            return Message.error("卡券有误", null);
        } else if (cardCoupon.getCardType().equals(CardType.BirthdayGift) || cardCoupon.getCardType().equals(CardType.QueenGift)) {
            Boolean received = this.isReceived(cardCoupon.getCardType(), userId);
            if (received) {
                logger.warn("该用户已经领取过;cardId=" + cardCoupon.getId() + ";cardType=" + cardCoupon.getCardType());
                return Message.error("亲，您已领取过。", null);
            }
        }

        return Message.success(null);
    }

    private void sendMailMsg(String msg) {
        try {
            mailUtil.sendWithHtml(
                    new String[]{"guohao@yiigoo.com,jiangyunbo@yiigoo.com,sunshuo@yiigoo.cn",}, "生成卡券验证", msg);
        } catch (Exception e1) {
            e1.printStackTrace();
        }
    }

    @Override
    public Message generateCardCoupon(Long userId, Long cardId, Long paymentCode, String remark) {

        YgCardCoupon cardCoupon = ygCardCouponService.findById(cardId);
        //砍价生成卡券需设置 skuId 值，使用下面方法
        Assert.isTrue(!CardType.KanJia.equals(cardCoupon.getCardType()), "砍价卡券不能使用该方法");
        return this.generateCardCoupon(userId, cardCoupon, paymentCode, remark, null);
    }

    @Override
    public Message generateCardCoupon(Long userId, YgCardCoupon cardCoupon, Long paymentCode, String remark, String sourceCode) {
        Message msg = checkCardCouponBeforeGenerate(userId, cardCoupon);
        if (msg.getType().equals(Message.Type.success)) {
            msg = generateCardCoupon(userId, cardCoupon, paymentCode, remark, null, sourceCode);
        }
        return msg;
    }

    private Message generateCardCoupon(Long userId, YgCardCoupon cardCoupon, Long paymentCode, String remark, Long parentId, String sourceCode) {
        paymentCode = ygFrameCodeService.getFrameCode(CodeType.RechargeMB, new Date());
        this.saveCardCouponDetail(userId, cardCoupon, paymentCode, remark);
        if (cardCoupon.getCardMode().equals(CardMode.Goods)) {
            List<YgSkuInfo> list = null;
            if (CardType.KanJia.equals(cardCoupon.getCardType())) {
                list = ygSkuService.findSkuInfoListByIds(Collections.singletonList(cardCoupon.getSkuId()));
            }
            if (org.apache.commons.collections4.CollectionUtils.isEmpty(list)) {
                list = ygSkuService.getSkuInfoList(Arrays.asList(cardCoupon.getProductIds()));
            }
            this.syncOrder(userId, paymentCode, parentId, true, sourceCode, list.get(0));
        } else if (cardCoupon.getCardMode().equals(CardMode.Coupon)) {
            YgUser user = ygUserService.findById(userId);
            sendCoupon(cardCoupon.getCouponId(), user, "女王,优惠券已奉上,请查收！");
        }
        return Message.success(null);

    }

    private void syncOrder(Long userId, Long paymentCode, Long parentId, boolean reduceStock, String sourceCode, YgSkuInfo... skuInfo) {
        threadPool.getExecutorService().execute(() -> {

            YgUserAddress addressInfo = YiigooAddressUtil.address;
            YgOrder order = saveGoodsCardOrder(userId, paymentCode, addressInfo, DataStatus.Delete, parentId, reduceStock, sourceCode, skuInfo);
//            try {
//                WdtQybResult wdtQybResult = wdtQybApi.tradePush(order);
//                ygOrderService.updateWdtCodeBatch(wdtQybResult.getPushSuccessList());
//            } catch (WdtException e) {
//                e.printStackTrace();
//            }

        });
    }

    @Override
    public Message shareCard(Long cardId, Long userId, String formId) {
        YgCardCouponDetail detail = this.findById(cardId, userId);
        if (detail == null || detail.getUserId().compareTo(userId) != 0) {
            return Message.error("亲您尚未拥有该卡券", cardId);
        }
        if (!detail.getUseStatus().equals(UseStatus.UnUsed)) {
            return Message.error("该卡券已使用，无法赠送", cardId);
        }
        if (detail.getSource().equals(CardSource.Presenter)) {
            return Message.error("该卡券为别人转赠，无法赠送", cardId);
        }
        if (detail.getCardType().equals(CardType.OrderGift)) {
            return shareCardByOrderGift(detail, formId);
        }
        /**
         * 该版本只可赠送下单购买的卡券
         * 2018-05-17
         */
        return Message.error("该类型卡券暂不支持赠送", cardId);
		/*Boolean gived = ygCardGiveRecordService.isByGived(cardId);
		if (gived) {
			return Message.error("该卡券为别人转赠，无法赠送", cardId);
		}
		Boolean received = ygCardGiveRecordService.isReceived(cardId, userId);
		if (received) {
			return Message.error("该卡券已被别人领取，无法赠送", cardId);
		}
		int i = ygCardGiveRecordService.addGiveRecord(cardId, userId);
		return Message.success(i);*/
    }

    private Message shareCardByOrderGift(YgCardCouponDetail mainCardDetail, String formId) {
        Long cardDetailId = mainCardDetail.getId();
        List<Long> subCardDetailIdList = findSubCardDetailIdList(cardDetailId);
        if (CollectionUtils.isEmpty(subCardDetailIdList)) {
            return Message.error("该卡券信息异常", cardDetailId);
        }
        int row = ygCardGiveRecordService.addBatchByCardDetailIdList(subCardDetailIdList, mainCardDetail.getUserId());
        this.updateRemarkById(cardDetailId, formId);
        return Message.success(row);
    }

    private int updateRemarkById(Long id, String remark) {
        YgCardCouponDetail detail = new YgCardCouponDetail();
        detail.setId(id);
        detail.setRemark(remark);
        return this.update(detail);
    }

    @Override
    public Message receiveCard(Long cardId, Long sharer, Long receiver) {
        YgCardCouponDetail cardDetail = this.findById(cardId);
        if (cardDetail == null || !cardDetail.getStatus().equals(DataStatus.Valid)) {
            return Message.error("该卡券不存在", cardId);
        }
        if (cardDetail.getUserId().compareTo(sharer) != 0) {
            return Message.error("参数异常，请稍后重试", JSONObject.parse("{cardId: " + cardId + ", sharer: " + sharer + "}"));
        }
        if (cardDetail.getCardType().equals(CardType.OrderGift)) { // 下单送红包
            return receiveCardByOrderGift(cardDetail, receiver);
        }
        int i = ygCardCouponDetailMapper.receiveCard(cardId, sharer, receiver);
        if (i == 1) {
            return Message.success("领取成功", i);
        }
        return Message.error("该卡券已被别人领取。", cardId);
    }

    @SuppressWarnings("unchecked")
    private Message receiveCardByOrderGift(YgCardCouponDetail mainCardDetail, Long receiveUserId) {
        Long cardDetailId = mainCardDetail.getId();
        if (mainCardDetail.getUseStatus().equals(UseStatus.Used)) {
            return Message.error("该卡券已被别人全部领取。", cardDetailId);
        }
        List<Long> subCardDetailIdList = findSubCardDetailIdList(cardDetailId);
        if (CollectionUtils.isEmpty(subCardDetailIdList)) {
            return Message.error("该卡券信息异常", cardDetailId);
        }
        Message received = ygCardGiveRecordService.validateGiveRecord(subCardDetailIdList, receiveUserId);
        if (!received.getType().equals(Message.Type.success)) {
            return received;
        }
        // 剩余可领取卡券
        List<YgCardGiveRecord> recordList = (List<YgCardGiveRecord>) received.getExtra();
        YgCardGiveRecord record = recordList.get(0);
        int i = ygCardCouponDetailMapper.receiveCard(record.getCardDetailId(), mainCardDetail.getUserId(), receiveUserId);
        if (i == 1) {
            if (recordList.size() <= 1) { // 全部赠送完，回写主卡券的使用状态，并发送小程序通知消息
                this.updateUseStatus(cardDetailId, UseStatus.Gived);
                sendWxSmallMsgToSharer(mainCardDetail.getUserId(), mainCardDetail.getRemark(), mainCardDetail.getProductName(), cardDetailId);
            }
            YgCardGiveRecord findByCardDetailId = ygCardGiveRecordService.findById(record.getId());
            return Message.success("领取成功", this.findById(findByCardDetailId.getNewCardDetailId()));
        }
        return Message.error("该卡券已被别人领取。", cardDetailId);
    }

    private List<Long> findSubCardDetailIdList(Long mainCardDetailId) {
        List<YgCardCouponDetail> subCardDetailList = this.findByRemark(null, mainCardDetailId.toString(), DataStatus.Delete);
        if (CollectionUtils.isEmpty(subCardDetailList)) {
            return new ArrayList<>();
        }
        return subCardDetailList.stream().map(o -> o.getId()).collect(Collectors.toList());
    }

    /**
     * 领取成功给发起人发送模板消息
     *
     * @param sharer
     * @param formId
     * @param productName
     * @param cardDetailId
     */
    private void sendWxSmallMsgToSharer(Long sharer, String formId, String productName, Long cardDetailId) {
        threadPool.getExecutorService().execute(new Runnable() {

            @Override
            public void run() {
                try {
                    YgUser shareUser = ygUserService.findById(sharer);
                    if (shareUser.getSmallOpenId() == null) {
                        logger.warn("领取成功给发起人发送小程序模板消息失败, 分享人【" + shareUser.getUserName() + "】无小程序opendid");
                        return;
                    }
                    String receiver = getReceiver(cardDetailId);
                    String title = "礼品领取成功通知";
                    String url = "pages/user/card/card?cardDetailId=" + cardDetailId;
                    Message message = wxSmallMessageService.sendGiftReceiveSuccessMsg(title, productName, new Date(), receiver, formId, url,
                            shareUser.getSmallOpenId());
                    if (!message.getType().equals(Message.Type.success)) {
                        logger.warn("领取成功给发起人发送小程序模板消息失败, " + message.getContent());
                    }
                } catch (Exception e) {
                    logger.error("领取成功给发起人发送小程序模板消息失败, " + ExceptionUtil.getExceptionMsg(e));
                }
            }
        });
    }

    private String getReceiver(Long cardDetailId) {
        List<CardCouponReceiver> list = this.findReceiverListByCardId(cardDetailId);
        StringBuffer sb = new StringBuffer();
        for (CardCouponReceiver receiver : list) {
            if (sb.length() != 0) {
                sb.append("、");
            }
            sb.append(receiver.getNickName());
        }
        return sb.toString();
    }

    private int updateUseStatus(Long cardId, UseStatus useStatus) {
        YgCardCouponDetail record = new YgCardCouponDetail();
        record.setId(cardId);
        record.setUseStatus(useStatus);
        record.setUseTime(new Date());
        return ygCardCouponDetailMapper.updateByPrimaryKeySelective(record);
    }

    @Override
    public YgCardCouponInfo findCardInfoByDetailId(Long cardDetailId) {
        return ygCardCouponDetailMapper.selectCardInfoByDetailId(cardDetailId);
    }

    @Override
    public Boolean isReceived(CardType cardType, Long userId) {
        YgUserMember member = ygUserMemberService.findByUserId(userId);

        if (member.getShippingEndTime() == null) {
            return true;
        }
        int diffYear = DateConvertUtils.diffYear(member.getMemberStartTime(), member.getShippingEndTime());
        int count = ygCardCouponDetailMapper.receivedCount(cardType, userId);
        if (count < diffYear) {
            return false;
        }
        return true;
    }

    @Override
    public YgCardCouponDetail findByUserIdAndRelationId(Long userId, Long relationId) {
        YgCardCouponDetailExample example = new YgCardCouponDetailExample();
        YgCardCouponDetailExample.Criteria criteria = example.createCriteria();
        if (userId != null) {
            criteria.andUserIdEqualTo(userId);
        }
        if (relationId != null) {
            criteria.andRelationIdEqualTo(relationId);
        }
        criteria.andStatusEqualTo(DataStatus.Valid.name());
        List<YgCardCouponDetail> list = ygCardCouponDetailMapper.selectByExample(example);
        return CollectionUtils.isEmpty(list) ? null : list.get(0);
    }

    @Override
    public List<YgCardCouponDetail> findByUnUsedCardCoupon() {
        return ygCardCouponDetailMapper.selectByUnUsedCardCoupon();
    }

    @Override
    public List<YgCardCouponDetail> findCardCouponList(Long userId, Long cardId, UseStatus useStatus, String startDate, String endDate, String overdueDate, CardType... types) {
        return ygCardCouponDetailMapper.selectCardCouponList(userId, cardId, useStatus, startDate, endDate, overdueDate, (types == null || types.length == 0) ? null : types);
    }

    @Override
    public List<YgCardCouponDetail> findCardCouponList(UseStatus useStatus, String startDate, String endDate, CardType... types) {
        return this.findCardCouponList(null, null, useStatus, startDate, endDate, null, types);
    }

    @Override
    public Message generateCardWithOrderId(Long orderId, Long count, String remark, Long userId) {
        YgOrder order = ygOrderService.findOrderDetailByOrderId(orderId);
        if (order == null || !order.getOrderType().equals(OrderType.CardCoupon)) {
            return Message.error("该订单无法生成卡券。", orderId);
        }
        if (order.getPaidTime() == null) {
            return Message.error("该订单未支付，无法生成卡券。", orderId);
        }
        List<YgOrderDetail> orderDetailList = order.getOrderDetail();
        if (CollectionUtils.isEmpty(orderDetailList)) {
            return Message.error("该订单信息异常，无订单明细。", orderId);
        }
        if (orderDetailList.get(0).getQuantity() % count != 0) {
            return Message.error("该订单sku数量异常,无法生成卡券。", JSONObject.parseObject("{orderId: " + orderId + ", count: " + count + "}"));
        }
        List<YgOrder> orderList = ygOrderService.findByParentId(orderId);
        if (!CollectionUtils.isEmpty(orderList)) {
            return Message.error("该订单已生成卡券，不能重复生成。", orderId);
        }
        Map<Long, List<YgOrderDetail>> map = orderDetailList.stream().collect(Collectors.groupingBy(YgOrderDetail::getSkuId));
        List<YgSkuInfo> skuList = ygSkuService.findSkuInfoListByIds(new ArrayList<>(map.keySet()));
        skuList.stream().forEach(o -> {
            o.setQuantity(map.get(o.getSkuId()).get(0).getQuantity() / count);
        });

        // 生成主卡券明细
        YgCardCouponDetail mainCardDetail = generateCardCouponDetailBySkuInfo(skuList, orderId, userId, remark, DataStatus.Valid, CardType.OrderGift);

        // 生成子卡券明细，生成新订单并推送
        for (int i = 0; i < count; i++) {
            YgCardCouponDetail couponDetail = generateCardCouponDetailBySkuInfo(skuList, null, userId, mainCardDetail.getId().toString(), DataStatus.Delete, CardType.OrderGift);
            this.syncOrder(userId, couponDetail.getRelationId(), orderId, false, null, skuList.toArray(new YgSkuInfo[skuList.size()]));
        }
        // 回写主订单状态
        YgOrder dbOrder = new YgOrder();
        dbOrder.setId(order.getId());
        dbOrder.setOrderStatus(OrderStatus.TradeSuccess);
        ygOrderService.update(dbOrder);
        return Message.success(mainCardDetail.getId());
    }

    private YgCardCouponDetail generateCardCouponDetailBySkuInfo(List<YgSkuInfo> skuList, Long orderId, Long userId, String remark, DataStatus status, CardType cardType) {
        if (orderId == null) {
            orderId = ygFrameCodeService.getFrameCode(CodeType.RechargeMB, new Date());
        }
        YgCardCouponDetail detail = new YgCardCouponDetail();
        detail.setCardType(cardType);
        detail.setCardMode(CardMode.Goods);
        detail.setCardId(0L);
        detail.setRelationId(orderId);
        setProductInfo(detail, skuList);
        detail.setCreateTime(new Date());
        detail.setUserId(userId);
        detail.setSource(CardSource.System);
        detail.setUseStatus(UseStatus.UnUsed);
        detail.setRemark(remark);
        detail.setStatus(status);
        Date now = new Date();
        detail.setStartDate(now);
        detail.setEndDate(DateConvertUtils.addDay(now, 29));
        this.save(detail);
        return detail;
    }

    @SuppressWarnings("unchecked")
    @Override
    public Message changeCardCouponRelationOrder(Long cardId, String changeSkuInfo, Long userId) {
        if (StringUtils.isBlank(changeSkuInfo)) {
            return Message.error("更换信息为空", cardId);
        }
        YgCardCouponDetail cardCouponDetail = this.findById(cardId);
        if (cardCouponDetail == null || cardCouponDetail.getUserId().compareTo(userId) != 0) {
            return Message.error("参数异常，请稍后重试", cardId);
        }
        if (cardCouponDetail.getUseStatus().equals(UseStatus.Used)) {
            return Message.error("该卡券已使用", cardId);
        }
        if (!cardCouponDetail.getSource().equals(CardSource.Presenter)) {
            return Message.error("暂只支持他人赠送的卡券可以更换", cardId);
        }
        YgOrder oldOrder = ygOrderService.findOrderDetailByOrderId(cardCouponDetail.getRelationId(), DataStatus.Delete);

        if (oldOrder.getUserId().compareTo(userId) == 0) {
            return Message.error("该卡券已更换过商品", cardId);
        }

        List<YgExchangeOrderDetail> changeList = JSON.parseArray(changeSkuInfo, YgExchangeOrderDetail.class);
        if (CollectionUtils.isEmpty(changeList)) {
            return Message.error("更换信息为空", cardId);
        }

        // 验证sku信息
        Message sourceSkuMsg = validateSkuChangeInfo(oldOrder, changeList);
        if (!sourceSkuMsg.getType().equals(Message.Type.success)) {
            return sourceSkuMsg;
        }
        List<YgSkuInfo> skuList = (List<YgSkuInfo>) sourceSkuMsg.getExtra();

        Long newOrderId = ygFrameCodeService.getFrameCode(CodeType.RechargeMB, new Date());
        YgOrder newOrder = saveNewOrderWithChange(newOrderId, userId, oldOrder.getParentId(), skuList);

        // 更新卡券详情信息
        setProductInfo(cardCouponDetail, skuList);
        cardCouponDetail.setRelationId(newOrderId);
        int row = this.update(cardCouponDetail);
        if (row > 0) { // 同步推送
            List<YgOrder> orders = new ArrayList<YgOrder>();
            oldOrder.setOrderStatus(OrderStatus.TradeClosed);
            orders.add(oldOrder);
            orders.add(newOrder);
            newOrder = ygOrderService.findOrderDetailByOrderId(newOrderId, DataStatus.Delete);
            this.syncOrderByChangeCard(orders);
        }
        Map<String, Object> data = new HashMap<>();
        data.put("sourceOrderId", oldOrder.getOrderId());
        data.put("newOrderId", newOrder.getOrderId());
        return Message.success(data);
    }

    /**
     * 处理更换sku信息，并生成新的sku信息集
     *
     * @param oldOrder
     * @param changeList
     * @return
     */
    private Message validateSkuChangeInfo(YgOrder oldOrder, List<YgExchangeOrderDetail> changeList) {
        Set<Long> skuIdSet = new HashSet<>();
        Map<Long, List<YgOrderDetail>> mapGrouping = oldOrder.getOrderDetail().stream().collect(Collectors.groupingBy(YgOrderDetail::getSkuId));
        Map<Long, Long> map = new HashMap<>();
        for (YgExchangeOrderDetail changeInfo : changeList) {
            Long sourceSkuId = changeInfo.getSourceSkuId();
            if (mapGrouping.get(sourceSkuId) == null) {
                return Message.error("更换信息中的sku不存在于原订单明细中", changeInfo.getSourceSkuId());
            }
            Long skuId = changeInfo.getSkuId();
            skuIdSet.add(skuId);
            // 统计更换的sku数量
            if (map.containsKey(skuId)) {
                map.put(skuId, map.get(skuId) + changeInfo.getAmount());
            } else {
                map.put(skuId, changeInfo.getAmount());
            }
            // 统计被更换的sku数量
            if (map.containsKey(sourceSkuId)) {
                map.put(sourceSkuId, map.get(sourceSkuId) - changeInfo.getAmount());
            } else {
                map.put(sourceSkuId, 0 - changeInfo.getAmount());
            }
        }
        for (Map.Entry<Long, List<YgOrderDetail>> entry : mapGrouping.entrySet()) {
            YgOrderDetail detail = entry.getValue().get(0);
            Long skuId = detail.getSkuId();
            // 统计原订单明细中的sku数量
            if (map.containsKey(skuId)) {
                map.put(skuId, map.get(skuId) + detail.getQuantity());
            } else {
                map.put(skuId, detail.getQuantity());
            }
            if (map.get(skuId) > 0) {
                skuIdSet.add(skuId);
            } else {
                skuIdSet.remove(skuId);
            }
        }
        List<YgSkuInfo> skuInfoList = ygSkuService.findSkuInfoListByIds(new ArrayList<>(skuIdSet));
        skuInfoList.stream().forEach(o -> {
            if (map.get(o.getSkuId()) != null) {
                o.setQuantity(map.get(o.getSkuId()));
            }
        });
        return Message.success(skuInfoList);
    }

    private void syncOrderByChangeCard(List<YgOrder> orders) {
        threadPool.getExecutorService().execute(() -> {
            try {
                wdtQybApi.tradePushBatch(orders);
            } catch (Exception e) {
                logger.error(ExceptionUtil.getExceptionMsg(e));
                e.printStackTrace();
            }
        });
    }

    private YgOrder saveNewOrderWithChange(Long orderId, Long userId, Long parentId, List<YgSkuInfo> skuList) {
        YgUserAddress addressInfo = YiigooAddressUtil.address;
        return saveGoodsCardOrder(userId, orderId, addressInfo, DataStatus.Delete, parentId, false, null, skuList.toArray(new YgSkuInfo[skuList.size()]));
    }

    private void setProductInfo(YgCardCouponDetail cardCouponDetail, List<YgSkuInfo> skuList) {
        String productIds = null;
        String productName = null;
        String color = null;
        BigDecimal price = null;
        String imagePath = null;
        for (YgSkuInfo sku : skuList) {
            if (productIds == null) {
                productIds = sku.getProductId().toString();
                productName = sku.getProductName();
                color = sku.getShortName();
                price = sku.getSalesPrice();
                imagePath = sku.getImgPath();
            } else {
                productIds = productIds + "," + sku.getProductId().toString();
            }
        }
        cardCouponDetail.setProductName(productName);
        cardCouponDetail.setColor(color);
        cardCouponDetail.setPrice(price);
        cardCouponDetail.setImagePath(imagePath);
    }

    @Override
    public List<YgCardCouponDetail> findByRemark(Long userId, String remark, DataStatus status) {
        if (StringUtils.isBlank(remark)) {
            return new ArrayList<>();
        }
        YgCardCouponDetailExample example = new YgCardCouponDetailExample();
        YgCardCouponDetailExample.Criteria criteria = example.createCriteria();
        if (userId != null) {
            criteria.andUserIdEqualTo(userId);
        }
        criteria.andRemarkEqualTo(remark).andStatusEqualTo(status == null ? DataStatus.Valid.name() : status.name());
        return ygCardCouponDetailMapper.selectByExample(example);
    }

    @Override
    public int transferCardCoupon(Long sourceUserId, Long targetUserId) {
        YgCardCouponDetailExample example = new YgCardCouponDetailExample();
        example.createCriteria().andUserIdEqualTo(sourceUserId);

        YgCardCouponDetail record = new YgCardCouponDetail();
        record.setUserId(targetUserId);
        return ygCardCouponDetailMapper.updateByExampleSelective(record, example);
    }

    @Override
    public List<CardCouponReceiver> findReceiverListByCardId(Long cardDetailId) {
        List<Long> subCardDetailIdList = findSubCardDetailIdList(cardDetailId);
        if (CollectionUtils.isEmpty(subCardDetailIdList)) {
            return new ArrayList<>();
        }
        return ygCardGiveRecordService.findUserListByCardDetailIdList(subCardDetailIdList);
    }

    @Override
    public int returnExpressCard(Long userId, Long relationId) {
        return ygCardCouponDetailMapper.updateByReturnExpress(userId, relationId);
    }

    @Override
    public int deleteByRelationId(List<Long> orderIdList) {
        if (CollectionUtils.isEmpty(orderIdList)) {
            return 0;
        }
        YgCardCouponDetail record = new YgCardCouponDetail();
        record.setStatus(DataStatus.Delete);
        YgCardCouponDetailExample example = new YgCardCouponDetailExample();
        example.createCriteria().andRelationIdIn(orderIdList).andStatusEqualTo(DataStatus.Valid.name());
        return ygCardCouponDetailMapper.updateByExampleSelective(record, example);
    }

    @Override
    public List<YgCardCouponInfo> findByCardIdAndUserId(Long cardId, Long userId) {
        return ygCardCouponDetailMapper.selectByCardIdAndUserId(cardId, userId);
    }

    @Override
    public List<YgUser> findReceiveUserListBySource(Long cardId, String sourceCode) {
        return ygCardCouponDetailMapper.selectReceiveUserListBySource(cardId, sourceCode);
    }

    @Override
    public Message cashCardByPayExpress(Long userId, Long cardDetailId, Long orderId, BigDecimal totalPrice, AppType appType, PayType payType, YgUserAddress address) {
        if (!ygUserService.isVip(userId)) {
            YgOrderPayment orderPayment = ygOrderPaymentService.findByOrderId(orderId);
            if (orderPayment == null || orderPayment.getPaySuccessTime() == null) {
                return Message.error("兑换失败，该卡券没有支付", null);
            }
        }
        YgCardCouponInfo card = this.findCardInfo(cardDetailId, userId);
        syncOrderByCashCard(userId, cardDetailId, orderId, card.getRelationId(), address, card.getProductIds(), totalPrice, totalPrice,
                appType, payType, null);
        YgCardCouponDetail ygCardCouponDetail = new YgCardCouponDetail();
        ygCardCouponDetail.setId(cardDetailId);
        ygCardCouponDetail.setUseStatus(UseStatus.Used);
        ygCardCouponDetail.setUseTime(new Date());
        this.update(ygCardCouponDetail);
        return Message.success(null);
    }

    @Deprecated
    @Override
    public void asyncGivePullNewCard(Long userId) {
		/* 新用户注册赠送拉新活动赠品已停用
		new Thread(new Runnable() {
			@Override
			public void run() {
				Message message = ygCardCouponService.validatePullNewCardCoupon();
				if (!Message.isSuccess(message)) {
					return;
				}
				YgCardCoupon cardCoupon = (YgCardCoupon) message.getExtra();
				Message generateCardCoupon = generateCardCoupon(userId, cardCoupon, null, null, null);
				if (!Message.isSuccess(generateCardCoupon)) {
					logger.error("新用户注册赠送拉新卡券异常，" + generateCardCoupon.getContent());
				}
			}
		}).start();*/
    }

    @Override
    public void generateCardCouponDetailBySku(String skuCode, Long userId, CardType cardType, String remark, BigDecimal cardPrice) {
        YgSkuInfo skuInfo = ygSkuService.getSkuInfo(skuCode, PromotionType.ManZeng);
        if (cardPrice != null) {
            skuInfo.setSalesPrice(cardPrice);
        }
        Long paymentCode = ygFrameCodeService.getFrameCode(CodeType.RechargeMB, new Date());
        generateCardCouponDetailBySkuInfo(Collections.singletonList(skuInfo), paymentCode, userId, remark, DataStatus.Valid, cardType);
        this.syncOrder(userId, paymentCode, null, true, null, skuInfo);
    }

    @Override
    public Message receiveCardCouponAction(Long userId, CardCouponAction actionInfo) {
        List<YgCardCouponDetail> list = this.findByRemark(userId, actionInfo.getSourceCode(), DataStatus.Valid);
        if (!CollectionUtils.isEmpty(list)) {
            return Message.success("新年快乐！北欧风毛线帽已放入您的账户，不可以重复领取。", null);
        }
        List<String> skuCodes = actionInfo.getSkuCodeListForGift();
        List<YgStock> stockList = ygStockService.findBySkuCodes(skuCodes.toArray(new String[0]));
        if (org.apache.commons.collections4.CollectionUtils.isEmpty(stockList)) {
            return Message.success("新年快乐！本活动赠品已送完，感谢关注。");
        }
        List<String> skuCodeList = stockList.stream().filter(o -> o.getAmount() > 0).map(YgStock::getSkuCode).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(stockList)) {
            return Message.success("新年快乐！本活动赠品已送完，感谢关注。");
        }
        String skuCode;
        String defaultSkuCode = actionInfo.getDefaultSkuCode();
        if (StringUtils.isNotBlank(defaultSkuCode) && skuCodeList.contains(defaultSkuCode)) {
            skuCode = defaultSkuCode;
        } else {
            skuCode = skuCodeList.get(0);
        }
        this.generateCardCouponDetailBySku(skuCode, userId, actionInfo.getCardType(), actionInfo.getSourceCode(), BigDecimal.ZERO);
        return Message.success("新年快乐！北欧风毛线帽已放入您的账户，现在就去领走吧", null);
    }

}
